﻿using System;
using System.Linq;
using CRM.Models.Email;
using CRM.ViewModels.Email;
using System.Threading.Tasks;
using Z.EntityFramework.Plus;
using System.Collections.ObjectModel;
using System.Text;
using Coravel.Cache.Interfaces;
using CRM.Extensions;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json;

namespace CRM.Services.Email
{
    public class EmailMarketingService : BaseService
    {

        /// <summary>
        /// 构造函数
        /// </summary>
        public EmailMarketingService()
        {
        }

        /// <summary>
        /// 修改定时任务时间 + 操作日志
        /// </summary>
        /// <param name="id"></param>
        /// <param name="timeNew"></param>
        /// <returns></returns>
        public async Task<bool> EditTimeTransmission(int id, DateTime timeNew)
        {
            var recordInfo = DbContext.EmailMarketing.FirstOrDefault(m => m.Id == id);
            if (recordInfo is not { IsLocked: false } ||
                recordInfo.State is EmailMarketing.StateEnum.Completed or EmailMarketing.StateEnum.Canceled)
                return false;
            var timeOld = recordInfo.TimingTransmission;
            // 改时间
            recordInfo.TimingTransmission = timeNew;
            // 加日志
            var operationContent = "将营销任务发送时间由 " + $"{timeOld}" + " 修改为 " + $"{timeNew}";
            var resultModel = new EmailMarkeingLogVM().NewModel(CurrentUser, id, EmailMarkeingLog.TypeEnum.Initiative,
                operationContent);
            DbContext.EmailMarkeingLog.Add(resultModel);
            // 保存数据
            await DbContext.SaveChangesAsync();
            return true;
        }

        /// <summary>
        /// 通过id获取营销任务详情
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public EmailMarketing GetInfoById(int id)
        {
            var result = DbContext.EmailMarketing.FirstOrDefault(m => m.Id == id);
            return result;
        }

        /// <summary>
        /// 设置营销任务状态 + 操作日志
        /// </summary>
        /// <param name="id"></param>
        /// <param name="state"></param>
        /// <returns></returns>
        public async Task<bool> SetState(int id, EmailMarketing.StateEnum state, EmailMarkeingLog.TypeEnum type,
            string message)
        {
            var transaction = await DbContext.Database.BeginTransactionAsync();
            try
            {
                // 改状态
                await DbContext.EmailMarketing.Where(m => m.Id == id).UpdateAsync(m => new { State = state });
                // 加日志
                var emailMarketingLogNewModel = new EmailMarkeingLogVM().NewModel(CurrentUser, id, type, message);
                DbContext.EmailMarkeingLog.Add(emailMarketingLogNewModel);
                // 保存数据
                await DbContext.SaveChangesAsync();
                await transaction.CommitAsync();
                return true;
            }
            catch (Exception e)
            {
                await transaction.RollbackAsync();
                Console.WriteLine("取消营销任务失败" + $"{e.Message}");
            }

            return false;
        }

        /// <summary>
        /// 创建营销任务 + 操作日志
        /// </summary>
        /// <param name="customers"></param>
        /// <param name="vm"></param>
        /// <returns></returns>
        public async Task<EmailMarketing> Create(Collection<Models.Customer> customers, EmailMarketingVM vm)
        {
            var model = vm.NewModel(DbContext, CurrentUser);

            try
            {
                DbContext.AttachRange(customers);
                model.Customers = customers;
                DbContext.EmailMarketing.Add(model);
                await DbContext.SaveChangesAsync();
            }
            catch (Exception e)
            {
                Error = e.Message;
                return null;
            }

            // 操作日志
            var resultModel = new EmailMarkeingLogVM().NewModel(CurrentUser, model.Id,
                EmailMarkeingLog.TypeEnum.Initiative, "创建营销任务");
            DbContext.EmailMarkeingLog.Add(resultModel);
            await DbContext.SaveChangesAsync();
            return model;
        }

        /// <summary>
        /// 锁定/解锁营销任务
        /// </summary>
        /// <param name="id"></param>
        /// <param name="isLocked"></param>
        /// <returns></returns>
        public async Task<bool> SetLockedStatus(int id, int userId, bool isLocked)
        {
            var result = false;

            var msg = "解锁";
            if (isLocked)
            {
                msg = "锁定";
            }

            try
            {
                var num = await DbContext.EmailMarketing.Where(m => m.Id == id)
                    .UpdateAsync(m => new() { IsLocked = isLocked });
                result = num > 0;
            }
            catch (Exception e)
            {
                Console.WriteLine("营销任务" + $"{msg}" + "失败" + $"{e.Message}");
                return false;
            }

            var user = DbContext.Users.FirstOrDefault(m => m.Id == userId);
            if (user != null)
            {
                // 操作日志
                var resultModel =
                    new EmailMarkeingLogVM().NewModel(user, id, EmailMarkeingLog.TypeEnum.Negative, "营销任务" + $"{msg}");
                DbContext.EmailMarkeingLog.Add(resultModel);
                await DbContext.SaveChangesAsync();
            }

            return result;
        }

        public async Task MarkEmailRead(int id, string email)
        {
            var row = await DbContext.EmailMarketing
                .Select(m => new EmailMarketing() { Id = m.Id, OpenNum = m.OpenNum, Addressee = m.Addressee })
                .FirstOrDefaultAsync(m => m.Id == id);
            if (row is null) return;

            var old = row.AddresseeObj;
            var item = old.FirstOrDefault(m => m.Addressee == email);
            if (item is null) return;
            DbContext.Attach(row);
            if (!item.IsRead)
            {
                DbContext.Entry(row).Increment(m => m.OpenNum, 1);
            }

            item.IsRead = true;
            row.Addressee = JsonConvert.SerializeObject(old);
            var history =
                await DbContext.EmailSendHistory.Select(m => new EmailSendHistory()
                        { Id = m.Id, Details = m.Details, Source = m.Source, ReceiverEmail = m.ReceiverEmail })
                    .FirstOrDefaultAsync(m => m.Source == id && m.ReceiverEmail == email);
            if (history is not null)
            {
                DbContext.Attach(history);
                history.Details |= (int)DetailsEnum.Open;
            }

            await DbContext.SaveChangesAsync();
        }

        public string BuildReadUrl(int id, string email)
        {
            return BuildReadUrl($"{Request.Scheme}://{Request.Host}", id, email);
        }
        
        public static string BuildReadUrl(string host,int id, string email)
        {
            return
                $"{host}/email/read?i={id}&r={System.Web.HttpUtility.UrlEncode(Convert.ToBase64String(Encoding.UTF8.GetBytes(email)))}";
        }
    }
}